﻿using Fleck;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WSLibrary
{
    using Fleck;
    using System.Threading;
    using WSLibrary.WebSocket;

    namespace WebSocket
    {
        internal class WebSocketHelper
        {
            //客户端url以及其对应的Socket对象字典
            IDictionary<string, IWebSocketConnection> dic_Sockets = new Dictionary<string, IWebSocketConnection>();
            //创建一个 websocket ,0.0.0.0 为监听所有的的地址
            WebSocketServer server = new WebSocketServer("ws://0.0.0.0:8088");

            //打开连接委托
            public delegate void _OnOpen(string ip);
            public event _OnOpen OnOpen;
            //关闭连接委托
            public delegate void _OnClose(string ip);
            public event _OnClose OnClose;
            //当收到消息
            public delegate void _OnMessage(string ip, string msg);
            public event _OnMessage OnMessage;

            /// <summary>
            /// 初始化
            /// </summary>
            private void Init()
            {
                //出错后进行重启
                server.RestartAfterListenError = true;

                //开始监听
                server.Start(socket =>
                {
                    //连接建立事件
                    socket.OnOpen = () =>
                    {
                        //获取客户端网页的url
                        string clientUrl = socket.ConnectionInfo.ClientIpAddress + ":" + socket.ConnectionInfo.ClientPort;
                        dic_Sockets.Add(clientUrl, socket);
                        if (OnOpen != null) OnOpen(clientUrl);
                        Console.WriteLine(DateTime.Now.ToString() + " | 服务器:和客户端:" + clientUrl + " 建立WebSock连接！");
                    };

                    //连接关闭事件
                    socket.OnClose = () =>
                    {
                        string clientUrl = socket.ConnectionInfo.ClientIpAddress + ":" + socket.ConnectionInfo.ClientPort;
                        //如果存在这个客户端,那么对这个socket进行移除
                        if (dic_Sockets.ContainsKey(clientUrl))
                        {
                            dic_Sockets.Remove(clientUrl);
                            if (OnClose != null) OnClose(clientUrl);
                        }
                        Console.WriteLine(DateTime.Now.ToString() + " | 服务器:和客户端:" + clientUrl + " 断开WebSock连接！");
                    };

                    //接受客户端网页消息事件
                    socket.OnMessage = message =>
                    {
                        string clientUrl = socket.ConnectionInfo.ClientIpAddress + ":" + socket.ConnectionInfo.ClientPort;
                        Receive(clientUrl, message);
                        if (OnMessage != null)
                            OnMessage(clientUrl, message);
                    };
                });
            }

            /// <summary>
            /// 向客户端发送消息
            /// </summary>
            /// <param name="webSocketConnection">客户端实例</param>
            /// <param name="message">消息内容</param>
            public void Send(string clientUrl, string message)
            {
                IWebSocketConnection webSocketConnection = GetUserSocketInstance(clientUrl);
                if (webSocketConnection != null)
                {
                    if (webSocketConnection.IsAvailable)
                    {
                        webSocketConnection.Send(message);
                    }
                }
            }

            /// <summary>
            /// 接收消息
            /// </summary>
            /// <param name="clientUrl"></param>
            /// <param name="message"></param>
            private void Receive(string clientUrl, string message)
            {
                Console.WriteLine(DateTime.Now.ToString() + " | 服务器:【收到】来客户端:" + clientUrl + "的信息：\n" + message);
            }

            /// <summary>
            /// 获取用户实例
            /// </summary>
            /// <param name="clientUrl">用户的地址</param>
            public IWebSocketConnection GetUserSocketInstance(string clientUrl)
            {
                if (dic_Sockets.ContainsKey(clientUrl))
                    return dic_Sockets[clientUrl];
                else
                    return null;
            }

            /// <summary>
            /// 关闭某一个用户的连接
            /// </summary>
            /// <param name="clientUrl"></param>
            public void CloseUserConnect(string clientUrl)
            {
                IWebSocketConnection webSocketConnection = GetUserSocketInstance(clientUrl);
                if (webSocketConnection != null)
                    webSocketConnection.Close();
            }

            /// <summary>
            /// 关闭与客户端的所有的连接
            /// </summary>
            public void CloseAllConnect()
            {
                foreach (var item in dic_Sockets.Values)
                {
                    if (item != null)
                    {
                        item.Close();
                    }
                }
            }

            public WebSocketHelper()
            {
                Init();
            }
        }
    }

        public class WSConfig
        {
            private static List<string> IPList = new List<string>();
            private static WebSocketHelper WebSocketHelpers = new WebSocketHelper();

            public static void Start()
            {
                WebSocketHelpers.OnOpen += WebSocketHelper_OnOpen;
                WebSocketHelpers.OnClose += WebSocketHelper_OnClose;
                WebSocketHelpers.OnMessage += WebSocketHelper_OnMessage;

                while (true)
                {
                    //监听控制台的输入
                    string contetn = Console.ReadLine();
                    if (contetn != null)
                    {
                        Relay(contetn);

                        if (contetn.Equals("q"))
                        {
                            WebSocketHelpers.CloseAllConnect();
                            Console.WriteLine("关闭所有客户端的连接");
                            break;
                        }
                    }
                    Thread.Sleep(10);
                }
            }

            #region WebSocket回调

            //当收到消息
            private static void WebSocketHelper_OnMessage(string ip, string msg)
            {
                for (int i = 0; i < IPList.Count; i++)
                {
                    if (IPList[i] != ip)
                    {
                        WebSocketHelpers.Send(IPList[i], msg);
                    }
                }
            }

            //当客户端断开连接
            private static void WebSocketHelper_OnClose(string ip)
            {
                if (IPList.Contains(ip))
                {
                    IPList.Remove(ip);
                }
            }

            //当客户端连接上服务器
            private static void WebSocketHelper_OnOpen(string ip)
            {
                if (!IPList.Contains(ip))
                {
                    IPList.Add(ip);
                }
            }

            #endregion

            //转发所有客户端
            public static void Relay(string content)
            {
                if (IPList.Count == 0) return;

                for (int i = 0; i < IPList.Count; i++)
                {
                    WebSocketHelpers.Send(IPList[i], content);
                }
            }
        }

}
